package com.sicau.socialpracticesystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sicau.socialpracticesystem.entity.param.pointexchange.PointsExchangeAddParam;
import com.sicau.socialpracticesystem.entity.param.pointexchange.PointsExchangeQueryParam;
import com.sicau.socialpracticesystem.entity.po.Points;
import com.sicau.socialpracticesystem.entity.po.PointsExchange;
import com.sicau.socialpracticesystem.entity.po.Prize;
import com.sicau.socialpracticesystem.mapper.PointsExchangeMapper;
import com.sicau.socialpracticesystem.service.PointsExchangeService;
import com.sicau.socialpracticesystem.service.PointsService;
import com.sicau.socialpracticesystem.service.PrizeService;
import com.sicau.socialpracticesystem.util.UserContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 * 积分使用记录表 服务实现类
 * </p>
 *
 * @author sxt && ttxxi
 * @since 2021-04-26
 */
@Service
public class PointsExchangeServiceImpl extends ServiceImpl<PointsExchangeMapper, PointsExchange> implements PointsExchangeService {

    @Resource
    PointsExchangeMapper pointsExchangeMapper;

    @Resource
    PrizeService prizeService;

    @Resource
    PointsService pointsService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addPointsExchange(PointsExchangeAddParam pointsExchangeAddParam) {

        Points points = pointsService.queryByUserId(UserContext.get().getId());
        //没有记录则直接返回
        if (points == null){
            return false;
        }

        Prize prize = prizeService.getById(pointsExchangeAddParam.getPrizeId());
        //没有prize或prize数量不够或积分不够兑换prize，则返回
        if (prize == null
                || prize.getPrizeNumber() < pointsExchangeAddParam.getNumber()
                || (points.getAllPoints() - points.getUsedPoints()) < prize.getNeedPoints()
        ){
            return false;
        }

        //更新，因为是在事物的条件下且根据id修改，所以必然会加行锁,但是事物只会保证不出错，无法保证是否会超额
        pointsService.consumePointById(points.getId(), pointsExchangeAddParam.getNumber() * prize.getNeedPoints());
        prizeService.updateNumberById(prize.getId(), pointsExchangeAddParam.getNumber());

        //保存兑换记录
        PointsExchange pointsExchange = new PointsExchange();
        pointsExchange.setPoints(pointsExchangeAddParam.getNumber() * prize.getNeedPoints());
        pointsExchange.setPrizeId(prize.getId());
        pointsExchange.setPrizeName(prize.getPriceName());
        pointsExchange.setUserId(UserContext.get().getId());
        pointsExchange.setUsedTime(LocalDateTime.now());
        pointsExchangeMapper.insert(pointsExchange);

        //再次查询，防止出现超额兑换
        points = pointsService.queryByUserId(UserContext.get().getId());
        prize = prizeService.getById(pointsExchangeAddParam.getPrizeId());
        if (prize.getPrizeNumber() < prize.getExchangedNumber()
                || points.getAllPoints() < points.getUsedPoints()
        ){
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        return true;
    }

    @Override
    public IPage<PointsExchange> queryPage(PointsExchangeQueryParam param) {
        Page<PointsExchange> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        LambdaQueryWrapper<PointsExchange> queryWrapper = new LambdaQueryWrapper<PointsExchange>()
                .eq(PointsExchange::getUserId, param.getUserId())
                .orderByDesc(PointsExchange::getId);
        return pointsExchangeMapper.selectPage(page, queryWrapper);
    }
}
